package net.sea.commons.util;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

/**
 * 文件操作类
 * 
 * @author 华成伍
 *
 */
public class FileUtils {
	/**
	 * 日志对象
	 */
	private static Logger logger = Logger.getLogger(FileUtils.class);
	/**
	 * 文件总大小
	 */
	private static long totalLength = 0;
	/**
	 * 完成大小
	 */
	private static long finishLength = 0;
	/**
	 * 是否第一次
	 */
	private static boolean isFirst = true;

	/**
	 * 把文件读取到字符串中
	 * 
	 * @param file
	 *            要读取的文件
	 * @return 文件内容
	 */
	public static String read(String file) {
		return read(new File(file));
	}

	/**
	 * 把文件读取到字符串中
	 * 
	 * @param file
	 *            要读取的文件
	 * @return 文件内容
	 */
	public static String read(File file) {
		StringBuffer data = new StringBuffer();
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(file));
			String str = "";
			while ((str = br.readLine()) != null) {
				// System.getProperty("line.separator")获取当前OS的换行符
				data.append(str).append(System.getProperty("line.separator"));
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					br = null;
				}
			}
		}
		return data.toString();
	}

	/**
	 * 从输入流中读取字符串
	 * 
	 * @param in
	 *            输入流
	 * @return 读取的字符串
	 */
	public static String read(InputStream in) {
		return read(in, "UTF-8");
	}

	/**
	 * 从输入流中读取字符串
	 * 
	 * @param in
	 *            输入流
	 * @param charSet
	 *            字符编码
	 * @return 读取的字符串
	 */
	public static String read(InputStream in, String charSet) {
		StringBuffer data = new StringBuffer();
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(in, charSet));
			String str = "";
			while ((str = br.readLine()) != null) {
				data.append(str).append(System.getProperty("line.separator"));
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					br = null;
				}
			}
		}
		return data.toString();
	}

	/**
	 * 把字符串写入指定文件中
	 * 
	 * @param str
	 *            要写入的字符串
	 * @param file
	 *            要输出的文件
	 */
	public static void wirte(String str, File file) {
		FileOutputStream fos = null;
		BufferedOutputStream bos = null;
		try {
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos);
			bos.write(str.getBytes());
			// 刷新缓存
			bos.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 关闭文件流
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
					fos = null;
				}
			}
			// 关闭缓存流
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
					bos = null;
				}
			}
		}
	}

	/**
	 * 复制文件
	 * 
	 * @param oriFile
	 *            原始文件
	 * @param destFile
	 *            目标文件
	 * @throws IOException
	 */
	public static void copy(String oriFile, String destFile) throws IOException {
		copy(new File(oriFile), new File(destFile));
	}

	/**
	 * 复制文件
	 * 
	 * @param oriFile
	 *            原始文件
	 * @param destFile
	 *            目标文件
	 * @throws IOException
	 */
	public static void copy(String oriFile, File destFile) throws IOException {
		copy(new File(oriFile), destFile);
	}

	/**
	 * 复制文件
	 * 
	 * @param oriFile
	 *            原始文件
	 * @param destFile
	 *            目标文件
	 * @throws IOException
	 */
	public static void copy(File oriFile, String destFile) throws IOException {
		copy(oriFile, new File(destFile));
	}

	/**
	 * 复制文件
	 * 
	 * @param oriFile
	 *            原始文件
	 * @param destFile
	 *            目标文件
	 * @throws IOException
	 */
	public static void copy(File oriFile, File destFile) throws IOException {
		// FileInputStream fis = null;
		// FileOutputStream fos = null;
		// BufferedInputStream bis = null;
		// BufferedOutputStream bos = null;
		// try {
		// fis = new FileInputStream(oriFile);
		// fos = new FileOutputStream(distFile);
		// bis = new BufferedInputStream(fis);
		// bos = new BufferedOutputStream(fos);
		// byte[] buffer = new byte[2048];
		// int length = 0;
		// while ((length = bis.read(buffer)) != -1) {
		// bos.write(buffer, 0, length);
		// }
		// bos.flush();
		// } catch (FileNotFoundException e) {
		// e.printStackTrace();
		// } catch (IOException e) {
		// e.printStackTrace();
		// } finally {
		// if (fis != null) {
		// try {
		// fis.close();
		// } catch (IOException e) {
		// e.printStackTrace();
		// fis = null;
		// }
		// }
		// if (fos != null) {
		// try {
		// fos.close();
		// } catch (IOException e) {
		// e.printStackTrace();
		// fos = null;
		// }
		// }
		// if (bis != null) {
		// try {
		// bis.close();
		// } catch (IOException e) {
		// e.printStackTrace();
		// bis = null;
		// }
		// }
		// if (bos != null) {
		// try {
		// bos.close();
		// } catch (IOException e) {
		// e.printStackTrace();
		// bos = null;
		// }
		// }
		// }
		if (logger.isDebugEnabled()) {
			logger.debug("源文件：" + oriFile + ",目标文件：" + destFile);
		}
		if (destFile != null) {
			File parentFile = destFile.getParentFile();
			if (parentFile != null && (!parentFile.exists())) {
				parentFile.mkdirs();
			}
		}

		// 处理第一次请求时的数据
		if (isFirst) {
			totalLength = 0;
			finishLength = 0;
			totalLength = getFileSize(oriFile);
			isFirst = false;
			if (totalLength == 0) {
				return;
			}
		}
		// 使用ANT的文件复制功能
		org.apache.tools.ant.util.FileUtils fileUtils = org.apache.tools.ant.util.FileUtils
				.getFileUtils();

		if (oriFile != null && oriFile.exists() && oriFile.isDirectory()
				&& destFile != null && destFile.isDirectory()) {
			copyDir(oriFile, destFile);
		} else {
			if (oriFile != null) {
				InstallMsgUtils.setInstallMsg("复制文件：" + oriFile.getName());
			}
			fileUtils.copyFile(oriFile, destFile);
			finishLength += getFileSize(oriFile);
			InstallMsgUtils
					.setInstallProcess((int) (finishLength * 100 / totalLength));
		}

	}

	/**
	 * 复制目录
	 * 
	 * @param oriFile
	 *            源目录
	 * @param destFile
	 *            目标目录
	 * @throws IOException
	 */
	private static void copyDir(File oriFile, File destFile) throws IOException {
		if (oriFile == null || (!oriFile.exists())) {
			throw new FileNotFoundException("源文件夹不存在");
		}
		if (destFile == null) {
			throw new FileNotFoundException("目标文件夹不存在");
		}
		if (oriFile.isDirectory()) {
			if (!destFile.exists()) {
				destFile.mkdirs();
			}
			if (destFile.isDirectory()) {
				File newFile = new File(destFile, oriFile.getName());
				newFile.mkdir();
				File[] childrenFile = oriFile.listFiles();
				for (File file : childrenFile) {
					copyDir(file, newFile);
				}
			}
		} else {
			if (destFile.isDirectory()) {
				copy(oriFile, new File(destFile, oriFile.getName()));
			} else {
				copy(oriFile, destFile);
			}
		}
	}

	/**
	 * 剪切文件
	 * 
	 * @param oriFile
	 *            原始文件
	 * @param distFile
	 *            目标文件
	 * @throws IOException
	 */
	public static void paste(String oriFile, String distFile)
			throws IOException {
		paste(new File(oriFile), new File(distFile));
	}

	/**
	 * 剪切文件
	 * 
	 * @param oriFile
	 *            原始文件
	 * @param distFile
	 *            目标文件
	 * @throws IOException
	 */
	public static void paste(String oriFile, File distFile) throws IOException {
		paste(new File(oriFile), distFile);
	}

	/**
	 * 剪切文件
	 * 
	 * @param oriFile
	 *            原始文件
	 * @param distFile
	 *            目标文件
	 * @throws IOException
	 */
	public static void paste(File oriFile, String distFile) throws IOException {
		paste(oriFile, new File(distFile));
	}

	/**
	 * 剪切文件
	 * 
	 * @param oriFile
	 *            原始文件
	 * @param distFile
	 *            目标文件
	 * @throws IOException
	 */
	public static void paste(File oriFile, File distFile) throws IOException {
		copy(oriFile, distFile);
		if (oriFile != null && oriFile.exists()) {
			oriFile.delete();
		}
	}

	/**
	 * 删除指定目录
	 * 
	 * @param dir
	 *            要删除的目录
	 */
	private static void deleteDir(File dir) {
		if (dir.isDirectory()) {
			File[] files = dir.listFiles();
			for (File file : files) {
				if (file.isDirectory()) {
					deleteDir(file);
				} else {
					file.delete();
				}
			}
		}
		dir.delete();
	}

	/**
	 * 删除指定文件（或文件夹）
	 * 
	 * @param file
	 *            要刪除的文件（或文件夹）
	 */
	public static void delete(File file) {
		if (file.isDirectory()) {
			deleteDir(file);
		} else {
			file.delete();
		}
	}

	/**
	 * 生产文件 如果文件所在路径不存在则生成路径
	 * 
	 * @param fileName
	 *            文件名 带路径
	 * @param isDirectory
	 *            是否为路径
	 * @return
	 */
	public static File buildFile(String fileName, boolean isDirectory) {
		File target = new File(fileName);
		if (isDirectory) {
			target.mkdirs();
		} else {
			if (!target.getParentFile().exists()) {
				target.getParentFile().mkdirs();
				target = new File(target.getAbsolutePath());
			}
		}
		return target;
	}

	/**
	 * 获取文件的大小
	 * 
	 * @param f
	 *            文件夹
	 * @return 文件夹大小
	 */
	public static long getFileSize(File f) {
		long size = 0;
		if (f != null && f.exists()) {
			if (f.isFile()) {
				return f.length();
			}
			File flist[] = f.listFiles();
			for (int i = 0; i < flist.length; i++) {
				if (flist[i].isDirectory()) {
					size = size + getFileSize(flist[i]);
				} else {
					size = size + flist[i].length();
				}
			}
		}
		return size;
	}

	/**
	 * 查找指定目录下的文件
	 * 
	 * @author 华成伍
	 * @param parentFile
	 *            父目录
	 * @param name
	 *            文件名
	 * @return 查找到的文件列表
	 */
	public static List<File> findFiles(File parentFile, String name) {
		// 判断指定目录是否为合法目录
		if (parentFile == null || (!parentFile.exists()) || parentFile.isFile()) {
			return null;
		}
		// 创建正则表达式
		final Pattern pattern = Pattern.compile(name.replace(".", "\\.")
				.replace("*", ".*"));
		return Arrays.asList(parentFile.listFiles(new FilenameFilter() {

			@Override
			public boolean accept(File dir, String fileName) {
				Matcher matcher = pattern.matcher(fileName);
				return matcher.find();
			}
		}));
	}

}
